﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Stone
{

    /// <summary>
    ///  http://wiki.openstreetmap.org/index.php/Slippy_map_tilenames
    /// </summary>
    public class Calculator
    {

        public static void getTiles(double lat, double lon, int zoom, ref int xtile, ref int ytile)
        {
            xtile = (int)Math.Floor((lon + 180) / 360 * (1 << zoom));
            ytile = (int)Math.Floor((1 - Math.Log(Math.Tan(lat * Math.PI / 180) + 1 / Math.Cos(lat * Math.PI / 180)) / Math.PI) / 2 * (1 << zoom));
        }

        public static void getLatLon(int x, int y, int zoom, ref double lat, ref double lon)
        {
            int n = getNumTiles(zoom);
            double relY = (double)y / (double)n;
            lat = getMercatorToLat(Math.PI * (1 - 2 * relY));
            lon = -180.0 + 360.0 * x / n;
        }

        private static int getNumTiles(int zoom)
        {
            return (int)Math.Pow(2.0, zoom);
        }

        /// <summary>
        /// http://www.demo2s.com/Code/CSharp/Language-Basics/ConvertingRadianstoDegrees.htm 
        /// </summary>
        /// <param name="mercatory"></param>
        /// <returns></returns>
        private static double getMercatorToLat(double mercatory)
        {
            return (180.0 / Math.PI) * (Math.Atan(Math.Sinh(mercatory)));
        }

        //      def xy2latlon(x,y,z):
        //      n = numTiles(z)
        //      relY = y / n
        //      lat = mercatorToLat(pi * (1 - 2 * relY))
        //      lon = -180.0 + 360.0 * x / n
        //      return(lat,lon)
        //
        //      def numTiles(z):
        //      return(pow(2,z))

        //      def mercatorToLat(mercatorY):
        //      return(degrees(atan(sinh(mercatorY))))

    }
}

